package cn.wen.javax.net.ftp;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.log4j.Logger;

import cn.wen.javax.crypto.Decryptable;

import it.sauronsoftware.ftp4j.FTPClient;

/**
 * Title：FTP 辅助类
 * <p>
 * Description：
 * <p>
 * Copyright：Copyright (c) 2010-2012
 * 
 * @author <a href="mailto:ct_wen@qq.com">ctwen</a>, 温承瑭
 * @version Revision：1.0 Date：2012/6/29 Description：初完成。
 *          <p>
 * @see cn.wen.javax.net.ftp4j.HelperOfFTP4J
 */
public class XFTPClient {

    public XFTPClient() {
	super();
    }

    public XFTPClient(String host, String username, String password) {
	super();
	this.host = host;
	this.username = username;
	this.password = password;
    }

    public XFTPClient(String host, int post, String username, String password) {
	super();
	this.host = host;
	this.post = post;
	this.username = username;
	this.password = password;
    }

    // -----------------------------------------------------------------------
    // the object members
    // -----------------------------------------------------------------------

    private final Logger log = Logger.getLogger(getClass());

    /**
     * FTP客户端。
     */
    private FTPClient client = null;

    /**
     * @return FTP客户端
     */
    public FTPClient getClient() {
	return client;
    }

    /**
     * 将已初始化的FTP客户端传入，作为操作基础。
     * 
     * @param client FTP客户端
     */
    public void setClient(FTPClient client) {
	this.client = client;
    }

    /**
     * 主机名/IP地址
     */
    private String host;

    /**
     * 端口号
     */
    private int post = 21;

    /**
     * FTP用户名
     */
    private String username;

    /**
     * FTP密码
     */
    private String password;
    private String internalPassword;
    
    /**
     * 解密器
     */
    private Decryptable decryptor;

    public String getHost() {
	return host;
    }

    public void setHost(String host) {
	this.host = host;
    }

    public int getPost() {
	return post;
    }

    public void setPost(int post) {
	this.post = post;
    }

    public String getUsername() {
	return username;
    }

    public void setUsername(String username) {
	this.username = username;
    }

    public String getPassword() {
	return password;
    }

    public void setPassword(String password) {
	this.password = password;
    }

    public void setDecryptor(Decryptable decryptor) {
        this.decryptor = decryptor;
    }

    // -----------------------------------------------------------------------
    // upload
    // -----------------------------------------------------------------------

    /**
     * <pre>
     * 将本地的指定资源上传到FTP服务器的目标位子。
     * </pre>
     * 
     * @param dst 远程目标文件或路径
     * @param src 本地指定文件或目录
     */
    public void upload(String dst, String src) {
	upload(dst, new File(src));
    }

    /**
     * <pre>
     * 将本地的指定资源上传到FTP服务器的目标位子。
     * </pre>
     * 
     * @param dst 远程目标文件或路径
     * @param src 本地指定文件或目录
     */
    public void upload(String dst, File src) {
	HelperOfFTP4J.upload(client, dst, src);
    }

    /**
     * <pre>
     * 将指定输入流以“流”方式上传为FTP服务器上的目标文件；
     * </pre>
     * 
     * @param client FTP客户端
     * @param dst 远程目标文件
     * @param src 指定输入流
     */
    public void upload(String dst, InputStream src) {
	upload(dst, src, 0l);
    }

    /**
     * <pre>
     * 将指定输入流以“流”方式上传为FTP服务器上的目标文件；
     * 该方法提供断点传输参数：
     * 	1.restartAt大于0时：启用断点传输，从restartAt指定的断点值开始上传；提前需要保证服务器支持这个功能！
     * 	2.restartAt等于0时：不用断点传输，采用普通方式上传。
     * </pre>
     * 
     * @param client FTP客户端
     * @param dst 远程目标文件
     * @param src 指定输入流
     * @param restartAt 断点传输值，等于零时表示采用普通方式下载。
     */
    public void upload(String dst, InputStream src, long restartAt) {
	HelperOfFTP4J.upload(client, dst, src, restartAt);
    }

    // -----------------------------------------------------------------------
    // download
    // -----------------------------------------------------------------------

    /**
     * <pre>
     * 从FTP服务器下载一个指定的资源到本地的目标位子；如果本地路径不存在则自动创建。
     * </pre>
     * 
     * @param src 远程指定文件或路径
     * @param dst 本地目标文件或目录
     */
    public void download(String src, String dst) {
	download(src, new File(dst));
    }

    /**
     * <pre>
     * 从FTP服务器下载一个指定的资源到本地的目标位子；如果本地路径不存在则自动创建。
     * </pre>
     * 
     * @param src 远程指定文件或路径
     * @param dst 本地目标文件或目录
     */
    public void download(String src, File dst) {
	HelperOfFTP4J.download(client, src, dst);
    }

    /**
     * <pre>
     * 从FTP服务器下载一个指定文件到目标输出流；
     * </pre>
     * 
     * @param src 远程指定文件
     * @param dst 目标输出流
     */
    public void download(String src, OutputStream dst) {
	download(src, dst, 0l);
    }

    /**
     * <pre>
     * 从FTP服务器下载一个指定文件到目标输出流；
     * 该方法提供断点传输参数：
     * 	1.restartAt大于0时：启用断点传输，从restartAt指定的断点值开始下载；提前需要保证服务器支持这个功能！
     * 	2.restartAt等于0时：不用断点传输，采用普通方式下载。
     * </pre>
     * 
     * @param src 远程指定文件
     * @param dst 目标输出流
     * @param restartAt 断点传输值，等于零时表示采用普通方式下载。
     */
    public void download(String src, OutputStream dst, long restartAt) {
	HelperOfFTP4J.download(client, src, dst, restartAt);
    }

    // -----------------------------------------------------------------------
    // other
    // -----------------------------------------------------------------------

    /**
     * 创建与目标主机的FTP连接。
     * @throws Exception 
     */
    public void connect() throws Exception {
	if (client != null) return;
	if (null == internalPassword) { // 初始内部密码。
	    if (null == decryptor) {
		internalPassword = password;
	    }
	    else { // 解密，获取明文密码。
		internalPassword = decryptor.decrypt(password);
	    }
	}
	client = HelperOfFTP4J.getFTPClient(host, post, username, internalPassword);
	log.debug("FTP客户端已准备就绪。");
    }

    /**
     * 创建FTP目录。
     * 
     * @param remotePath 远程目标路径
     */
    public void createDirectory(String remotePath) {
	HelperOfFTP4J.createDirectory(client, remotePath);
    }

    /**
     * 切换到指定FTP目录。
     * 
     * @param client FTP客户端
     * @param remotePath 远程目标路径
     */
    public void changeDirectory(String remotePath) {
	HelperOfFTP4J.changeDirectory(client, remotePath);
    }

    /**
     * 删除FTP服务器上的指定文件或目录。 注：该方法仅支持删除非空目录。
     * 
     * @param remotePath 远程目标文件或目录
     */
    public void delete(String remotePath) {
	HelperOfFTP4J.delete(client, remotePath);
    }

    /**
     * <pre>
     * 判断一个FTP路径是否存在；
     * 如果存在返回类型(FTPFile.TYPE_FILE=0、FTPFile.TYPE_DIRECTORY=1、FTPFile.TYPE_LINK=2) 如果文件不存在，则返回一个-1。
     * </pre>
     * 
     * @param client FTP客户端
     * @param remotePath FTP文件或文件夹路径
     * @return 存在时候返回类型值(文件0，文件夹1，连接2)，不存在则返回-1
     */
    public int isExist(String remotePath) {
	return HelperOfFTP4J.isExist(client, remotePath);
    }

    /**
     * 关闭FTP连接，关闭时候像服务器发送一条关闭命令。
     * 
     * @return 关闭成功，或者链接已断开，或者链接为null时返回true，否则返回false。
     */
    public void disconnect() {
	HelperOfFTP4J.closeQuietly(client);
	client = null;
	log.debug("FTP客户端成功关闭！");
    }

}
